﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>轨迹图</title>
    <link href="../../../DataUser/Style/ccbpm.css" rel="stylesheet" type="text/css" />
    <script src="../../Scripts/Raphael/raphael.js" type="text/javascript"></script>
    <script src="../../Scripts/easyUI/jquery-1.8.0.min.js" type="text/javascript"></script>
    <script src="../../Scripts/designer.utility.js" type="text/javascript"></script>
    <script src="../../Scripts/config.js" type="text/javascript"></script>
    <script src="../../Comm/Gener.js" type="text/javascript"></script>
    <script src="../../Admin/CCFlowEnum.js" type="text/javascript"></script>
    <script src="TimeBase.js?s=xxx" type="text/javascript"></script>
</head>
<body>
    <style type="text/css">
        #holder
        {
            /*width: 1000px;
            height: 600px;*/
            margin: 10px; /*border: 1px dashed #c0c0c0;*/
        }
    </style>
  
    <script type="text/javascript">

        var jdata;
        var rFlow;
        var r;
        var arrs = [];
        var linedots = [];
        var dragNode;
        var dragBorderPointStart;
        var dragTextPointStart;
        var dragTrackTextPointStart;
        var dragPossibleTextPointStart;
        var isSubFlowNode;

        //定义样式变量，可在此统一修改流程样式
        var STYLE_CANVAS_COLOR = '#FFFFFF'; //画布背景颜色,E7F1F9
        var STYLE_FONT_SIZE_NODE = 14;  //节点名称字体大小
        var STYLE_FONT_SIZE_LABEL = 12; //标签字体大小

        var STYLE_NODE_WIDTH = 50;  //节点宽度
        var STYLE_NODE_HEIGHT = 50; //节点高度
        var STYLE_NODE_COLOR_FORE = 'Gray';    //节点名称颜色
        var STYLE_NODE_COLOR_FORE_HOVER = 'blue';   //节点名称鼠标悬停时颜色
        var STYLE_NODE_COLOR_FORE_TRACK = 'green';    //走过的节点名称颜色
        var STYLE_NODE_DEFAULT_ICON_PATH = '../../../DataUser/NodeIcon/'; //默认节点图标所在相对路径
        var STYLE_NODE_DEFAULT_ICON = 'Default.jpg';    //默认节点图标文件名称
        var STYLE_NODE_BORDER_RADIUS = 5;   //节点边框圆角大小
        var STYLE_NODE_BORDER_COLOR_FIRST = 'green';    //开始节点边框颜色
        var STYLE_NODE_BORDER_COLOR_END = 'red';    //结束节点边框颜色
        var STYLE_NODE_BORDER_COLOR = 'black';  //节点边框颜色
        var STYLE_NODE_BORDER_COLOR_HOVER = 'blue'; //节点边框鼠标悬停时颜色
        var STYLE_NODE_BORDER_COLOR_TRACK = 'green';  //走过的节点边框颜色
        var STYLE_NODE_BORDER_WIDTH_NORMAL = 1; //节点边框宽度
        var STYLE_NODE_BORDER_WIDTH_HOVER = 3;  //节点边框鼠标悬停时的宽度

        var STYLE_LABEL_COLOR_FORE = 'none';    //标签字体颜色

        var STYLE_LINE_COLOR = 'Gray'; //连线颜色
        var STYLE_LINE_HOVER_COLOR = 'blue';    //连线鼠标悬停时的颜色
        var STYLE_LINE_WIDTH = 1;   //连线宽度
        var STYLE_LINE_TRACK_COLOR = 'green'; //走过的连线颜色
        var STYLE_NODE_TRACK_FONT_SIZE = 14;    //走过的节点轨迹信息字体大小
        var STYLE_NODE_TRACK_FORE_COLOR = 'green';    //走过的节点轨迹信息字体颜色
        //var DATA_USER_ICON_PATH = '/ccflow5/DataUser/UserIcon/';
        var DATA_USER_ICON_PATH = '../../../DataUser/UserIcon/';    //用户头像文件相对目录
        var DATA_USER_ICON_DEFAULT = 'Default.png'; //默认用户头像文件名称
        var DATA_MULTI_USER_ICON_DEFAULT = '../../Img/Multiplayer.png'; //多用户头像文件相对路径

        var fk_Flow;
        var work_ID;
        var fid;
        var uh = new UrlHerf(location.href);
        $(function () {
            fk_Flow = uh["FK_Flow"];
            work_ID = uh["WorkID"];
            fid = uh["FID"];

            if (!work_ID || work_ID == "null") {
                work_ID = "0";
            }

            if (!fid || fid == "null") {
                fid = "0";
            }

            var handler = new HttpHandler("BP.WF.HttpHandler.WF_WorkOpt_OneWork");
            handler.AddPara("FK_Flow", fk_Flow);
            handler.AddPara("WorkID", work_ID);
            handler.AddPara("FID", fid);

            var data = handler.DoMethodReturnString("Chart_Init");

            if (data.indexOf('err@') == 0) {
                alert(data);
                return;
            }

            jdata = $.parseJSON(data);

            DrawStart(jdata); //执行绘制信息.
        });

        ///开始绘制.
        function DrawStart(datas) {

            /// <summary>加载时绘制流程图/轨迹</summary>
            /// <param name="datas" Type="Object">绘制的数据，包含flow/nodes/labels/dirs/tracks，均为Array</param>

            $('#holder').css('background-color', STYLE_CANVAS_COLOR);

            var width = $(document).width();
            var height = $(document).height();
            var max = getMaxSize(datas.WF_Node, datas.WF_Direction);

            if (height < 600) {
                height = 600;
            }

            r = Raphael('holder', Math.max(width, max.X) + 100, Math.max(height, max.Y) + 50);
            var rNode, rDir, rBorder, rImage, rText, rLabel, rPath;

            rFlow = new RFlow(fk_Flow);

            //绘制节点
            var nodeBorderColor = STYLE_NODE_BORDER_COLOR;
            var startNodePosType = 0;
            var endNodePosType = getMaxInArray(datas.WF_Node, 'NodePosType');
            var nodeTracks;
            var nodeTrack;
            var isExist;

            $('#tracktable').hover(function () { }, function () {
                $('#trackinfo').offset({ top: 0, left: 0 });
                $('#trackinfo').hide();
            });

            $.each(datas.WF_Node, function () {

                //确定边框颜色
                switch (this.NODEPOSTYPE) {
                    case startNodePosType:
                        nodeBorderColor = STYLE_NODE_BORDER_COLOR_FIRST;
                        break;
                    case endNodePosType:
                        nodeBorderColor = STYLE_NODE_BORDER_COLOR_END;
                        break;
                    default:
                        nodeBorderColor = STYLE_NODE_BORDER_COLOR;
                        break;
                }

                //检测轨迹数据，如果有，则将该节点图标换成处理人头像，人名绘制于节点图标的右侧.
                nodeTracks = getTracksByFromNode(datas.Track, this.ID);
                if (nodeTracks.length > 0) {
                    nodeTrack = getTrackForCurrNode(nodeTracks);
                }
                else {
                    nodeTrack = null;
                }

                //确定节点图标
                if (nodeTrack != null) {
                    this.ICON = DATA_USER_ICON_PATH + (nodeTrack.type == "FROM" ? nodeTrack.track.EmpFrom : nodeTrack.track.EmpTo) + '.png';

                    isExist = checkUrl(encodeURI(this.ICON));
                    if (isExist == false) {
                        this.ICON = DATA_USER_ICON_PATH + DATA_USER_ICON_DEFAULT;
                    }
                }
                else {
                    if (this.ICON == null || this.ICON.length == 0) {
                        this.ICON = STYLE_NODE_DEFAULT_ICON_PATH + STYLE_NODE_DEFAULT_ICON;
                    }
                    else {
                        if (this.ICON.indexOf('.') == -1) {
                            this.ICON = STYLE_NODE_DEFAULT_ICON_PATH + this.ICON + '.png';
                        }
                        else {
                            this.ICON = STYLE_NODE_DEFAULT_ICON_PATH + this.ICON.substr(this.ICON.lastIndexOf('/') + 1);
                        }

                        isExist = checkUrl(encodeURI(this.ICON));
                        if (isExist == false) {
                            this.ICON = STYLE_NODE_DEFAULT_ICON_PATH + STYLE_NODE_DEFAULT_ICON;
                        }
                    }
                }

                //开始绘制
                rNode = new RNode(this.ID, this.Name, this.X - STYLE_NODE_WIDTH / 2, this.Y - STYLE_NODE_HEIGHT / 2);
                rNode.rBorder = r.rect(rNode.x, rNode.y, STYLE_NODE_WIDTH, STYLE_NODE_HEIGHT, STYLE_NODE_BORDER_RADIUS);
                // rNode.rIcon = r.image(this.ICON, rNode.x + 1, rNode.y + 1, STYLE_NODE_WIDTH - 2, STYLE_NODE_HEIGHT - 2);
                rNode.rIcon = r.image(this.ICON, rNode.x + 1, rNode.y + 1, STYLE_NODE_WIDTH - 2, STYLE_NODE_HEIGHT - 2);

                rNode.rText = r.text(rNode.x + STYLE_NODE_WIDTH / 2, rNode.y + STYLE_NODE_HEIGHT + Math.ceil(this.Name.length / 7.00) * 7 + 10, breakstr(this.Name, 7));    //edited by liuxc,2016-3-31,增加节点名称换行处理

                // rNode.rText = this.Name;
                //  rNode.rBorderColor = nodeBorderColor;


                rNode.isTrackNode = nodeTrack != null;
                rNode.tracks = nodeTracks;
                rNode.currTrack = nodeTrack;

                //在节点右侧绘制流程轨迹中当前节点的处理人/处理时间
                if (rNode.isTrackNode) {
                    //判断此节点是否是多人处理
                    if (rNode.currTrack.track.EmpToT.indexOf('多人接受') > -1) {
                        //alert(rNode.currTrack.track.EMPTOT);
                        this.ICON = DATA_MULTI_USER_ICON_DEFAULT;
                        rNode.rIcon.attr("src", this.ICON);
                    }

                    rNode.rTrackText = r.text(rNode.x + STYLE_NODE_WIDTH + 5, rNode.y + 25, rNode.currTrack.type == "FROM" ? (rNode.currTrack.track.EmpFromT + '\n' + getChineseDateTime(rNode.currTrack.track.RDT)) : rNode.currTrack.track.EmpToT);
                    rNode.rTrackText.attr({ "stroke": STYLE_NODE_TRACK_FORE_COLOR, "fill": getFillTextColor(STYLE_NODE_TRACK_FORE_COLOR), "font-size": STYLE_NODE_TRACK_FONT_SIZE, "text-anchor": "start" });
                    rNode.rTrackText.toFront();
                }
                else if (datas.Possible) {

                    //检索是否有计算出节点处理人，以及可能处理时间，有则显示出来，added by liuxc,2016-4-15
                    rNode.rPossible = datas.Possible.findByField("FK_Node", this.ID);

                    if (rNode.rPossible) {
                        rNode.rPossibleText = r.text(rNode.x + STYLE_NODE_WIDTH + 5, rNode.y + 25, "处理人：" + rNode.rPossible.EmpName + (rNode.rPossible.ADT && rNode.rPossible.ADT.length >= 16 ? ('\n到达：' + rNode.rPossible.ADT) : ''));
                        rNode.rPossibleText.attr({ "stroke": STYLE_NODE_TRACK_FORE_COLOR, "fill": getFillTextColor(STYLE_NODE_TRACK_FORE_COLOR), "font-size": STYLE_NODE_TRACK_FONT_SIZE, "text-anchor": "start" });
                        rNode.rPossibleText.toFront(); FrmWorkCheck
                    }
                }

                rNode.rBorder.attr({ "stroke": (rNode.currTrack ? STYLE_NODE_BORDER_COLOR_TRACK : nodeBorderColor), "stroke-width": STYLE_NODE_BORDER_WIDTH_NORMAL });
                rNode.rText.attr({ "stroke": (rNode.currTrack ? STYLE_NODE_COLOR_FORE_TRACK : STYLE_NODE_COLOR_FORE), "fill": getFillTextColor(rNode.currTrack ? STYLE_NODE_COLOR_FORE_TRACK : STYLE_NODE_COLOR_FORE), "font-size": STYLE_FONT_SIZE_NODE });
                rNode.rIcon.attr("title", this.Name);

                //增加节点图片的鼠标滑过/移开效果
                rNode.rIcon.hover(function () {

                    $('#tracktable').empty();
                    var node = rFlow.getNodeByRIconId(this.id);
                    var Tracks = jdata.Track;
                    //审核组件信息.
                    var fwc = jdata.FrmWorkCheck;

                    if (node != null) {
                        node.rBorder.attr({ "stroke": STYLE_NODE_BORDER_COLOR_HOVER, "stroke-width": STYLE_NODE_BORDER_WIDTH_HOVER });
                        node.rText.attr({ "stroke": STYLE_NODE_COLOR_FORE_HOVER, "fill": getFillTextColor(STYLE_NODE_COLOR_FORE_HOVER) });

                        var tablehtml = "";
                        //                        //是否有审核组件?
                        //                        var isHaveCheck = false;
                        //                        for (var i = 0; i < Tracks.length; i++) {

                        //                            var track = Tracks[i];

                        //                            // 记录审核节点。
                        //                            if (track.ActionType == ActionType.WorkCheck) {
                        //                                isHaveCheck = true;
                        //                                break;
                        //                            }
                        //                        }
                        //                        for (var i = 0; i < Tracks.length; i++) {

                        //                            var track = Tracks[i];
                        //                            if (track.FID != 0)
                        //                                continue;

                        //                            if (track.ActionType == ActionType.FlowBBS)
                        //                                continue;
                        //                            if (track.ActionType == ActionType.WorkCheck)
                        //                                continue;

                        //                            if (track.NDFrom != node.id)
                        //                                continue;

                        //                            //时间轴.
                        //                            var timeBase = "";
                        //                            var img = ActionTypeStr(track.ActionType);
                        //                            img = "<img src='" + img + "' width='10px;' class='ImgOfAC' alt='" + track.ActionTypeText + "'  />";

                        //                            //是否显示审批意见？
                        //                            var isShowCheckMsg = true;
                        //                            if (fwc.FWCMsgShow == "1" && track.NDFrom == GetQueryString("FK_Node") && webUser.No != track.EmpTo) {
                        //                                continue;
                        //                                isShowCheckMsg = false;
                        //                            }

                        //                            //内容.
                        //                            tablehtml += "<tr style='background-color:InfoBackground' >";
                        //                            tablehtml += "<td>" + track.NDFromT + "</td>";
                        //                            tablehtml += "<td>" + track.ActionTypeText + "</td>";
                        //                            tablehtml += "</tr>";
                        //                            var at = track.ActionType;

                        //                            if (at == ActionType.Return) {
                        //                                tablehtml += "<tr style='background-color:InfoBackground' >";
                        //                                tablehtml += "<td><span>退回到:</span></td>";
                        //                                tablehtml += "<td><font color=green>" + track.NDToT + "</font><td>";
                        //                                tablehtml += "</tr>";
                        //                                tablehtml += "<tr style='background-color:InfoBackground' >";
                        //                                tablehtml += "<td><span>退回给:</span></td>";
                        //                                tablehtml += "<td><font color=green>" + track.EmpToT + "</font></td>>";
                        //                                tablehtml += "</tr>";
                        //                                tablehtml += "<tr>";
                        //                                tablehtml += "<td colspan='2'><span>退回意见如下</span>  </td>";
                        //                                tablehtml += "</tr>";
                        //                            }

                        //                            if (at == ActionType.Forward) {
                        //                                tablehtml += "<tr style='background-color:InfoBackground' >";
                        //                                tablehtml += "<td><span>到达节点:</span></td>";
                        //                                tablehtml += "<td><font color=green>" + track.NDToT + "</font></td>";
                        //                                tablehtml += "</tr>";
                        //                                tablehtml += "<tr style='background-color:InfoBackground' >";
                        //                                tablehtml += "<td><span>到达人员:</span></td>";
                        //                                tablehtml += "<td><font color=green>" + track.EmpToT + "</font> </td>";
                        //                                tablehtml += "</tr>";

                        //                                //找到该节点，该人员的审核track, 如果没有，就输出Msg, 可能是焦点字段。
                        //                                for (var myIdx = 0; myIdx < Tracks.length; myIdx++) {

                        //                                    var checkTrack = Tracks[myIdx];
                        //                                    if (checkTrack.NDFrom == track.NDFrom && checkTrack.ActionType == ActionType.WorkCheck && checkTrack.EmpFrom == track.EmpFrom) {
                        //                                        ttablehtml += "<tr style='background-color:InfoBackground' >";
                        //                                        tablehtml += "<td colspan='2'><span>审批意见：</span></td>";
                        //                                        tablehtml += "</tr>";
                        //                                        tablehtml += "<tr>";
                        //                                        tablehtml += "<td colspan='2'><font color=green>" + checkTrack.Msg + "</font> </td>";
                        //                                        tablehtml += "</tr>";
                        //                                    }
                        //                                }
                        //                            }

                        //                            //协作发送.
                        //                            if (at == ActionType.TeampUp) {

                        //                                for (var myIdx = 0; myIdx < Tracks.length; myIdx++) {

                        //                                    var checkTrack = Tracks[myIdx];
                        //                                    if (checkTrack.NDFrom == track.NDFrom && checkTrack.ActionType == ActionType.WorkCheck && checkTrack.EmpFrom == track.EmpFrom) {
                        //                                        tablehtml += "<tr style='background-color:InfoBackground' >";
                        //                                        tablehtml += "<td><span colspan='2'>会签意见：</span></td>";
                        //                                        tablehtml += "</tr>";
                        //                                        tablehtml += "<tr>";
                        //                                        tablehtml += "<td colspan='2'><font color=green>" + checkTrack.Msg.replace('null', '') + "</font> </td>";
                        //                                        tablehtml += "</tr>";
                        //                                    }
                        //                                }
                        //                            }

                        //                            //输出备注信息.
                        //                            var tag = track.Tag;
                        //                            if (tag != null)
                        //                                tag = tag.replace("~", "'");

                        //                            var msg = track.Msg;
                        //                            if (msg == "0")
                        //                                msg = "";

                        //                            if (msg != "") {

                        //                                while (msg.indexOf('\t\n') >= 0) {
                        //                                    msg = msg.replace('\t\n', '<br>');
                        //                                }

                        //                                msg = msg.replace('null', '');

                        //                                if (msg == "" || msg == undefined)
                        //                                    msg = "无";
                        //                                tablehtml += "<tr>";
                        //                                tablehtml += "<td colspan='2'>";
                        //                                tablehtml += "<font color=green><br>" + msg + "</font><br>";
                        //                                tablehtml += "</td>";
                        //                                tablehtml += "</tr>";
                        //                            }

                        //                        }


                        //                        //增加等待审核的人员, 在所有的人员循环以后.
                        //                        var gwls = jdata.WF_GenerWorkerList;
                        //                        if (gwls) {
                        //                            var isHaveNoChecker = false;
                        //                            var gwl = null;
                        //                            for (var i = 0; i < gwls.length; i++) {

                        //                                var gwl = gwls[i];
                        //                                if (gwl.FK_Node != node.id)
                        //                                    continue;
                        //                                if (gwl.IsPass == 1)
                        //                                    continue;

                        //                                isHaveNoChecker = true;
                        //                            }

                        //                            //如果有尚未审核的人员，就输出.
                        //                            if (isHaveNoChecker == true) {

                        //                                for (var i = 0; i < gwls.length; i++) {
                        //                                    var html = "";

                        //                                    var gwl = gwls[i];
                        //                                    if (gwl.IsPass == 1)
                        //                                        continue;

                        //                                    tablehtml += "<tr style='background-color:InfoBackground' >";
                        //                                    tablehtml += "<td><span>审批人</span></td>";
                        //                                    tablehtml += "<td>" + gwl.FK_EmpText + "</td>";
                        //                                    tablehtml += "</tr>";
                        //                                    tablehtml += "<tr style='background-color:InfoBackground' >";
                        //                                    tablehtml += "<td><span>阅读状态:</span></td>";

                        //                                    if (gwl.IsRead == "1")
                        //                                        tablehtml += "<td><span><font color=green>已阅读.</font></span></td>";
                        //                                    else
                        //                                        tablehtml += "<td><span><font color=green>尚未阅读.</font></span></td>";

                        //                                    tablehtml += "</tr>";
                        //                                    tablehtml += "<tr style='background-color:InfoBackground' >";
                        //                                    tablehtml += "<td><span>工作到达日期:</span></td>";
                        //                                    tablehtml += "<td>" + gwl.RDT + "</td>";
                        //                                    tablehtml += "</tr>";

                        //                                    //到达时间.
                        //                                    var toTime = gwl.RDT;
                        //                                    var toTimeDot = toTime.replace(/\-/g, "/");
                        //                                    toTimeDot = new Date(toTimeDot);

                        //                                    //当前发生日期.
                        //                                    timeDot = new Date();


                        //                                    tablehtml += "<tr style='background-color:InfoBackground' >";
                        //                                    tablehtml += "<td><span>已经耗时:</span></td>";
                        //                                    tablehtml += "<td>" + GetSpanTime(toTimeDot, timeDot) + "</td>";
                        //                                    tablehtml += "</tr>";

                        //                                    tablehtml += "<tr style='background-color:InfoBackground' >";
                        //                                    tablehtml += "<td><span>应完成日期:</span></td>";
                        //                                    tablehtml += "<td>" + gwl.SDT + "</td>";
                        //                                    tablehtml += "</tr>";


                        //                                    //应该完成日期.
                        //                                    toTime = gwl.SDT;
                        //                                    toTimeDot = toTime.replace(/\-/g, "/");
                        //                                    toTimeDot = new Date(toTimeDot);

                        //                                    //当前发生日期.
                        //                                    timeDot = new Date();

                        //                                    var timeLeft = GetSpanTime(timeDot, toTimeDot);

                        //                                    if (timeLeft != 'NaN秒') {
                        //                                        tablehtml += "<tr style='background-color:InfoBackground' >";
                        //                                        tablehtml += "<td><span>还剩余:</span></td>";
                        //                                        tablehtml += "<td>" + timeLeft + "</td>";
                        //                                    }
                        //                                }
                        //                            }
                        //                        }

                        //                        tablehtml += "</table>";

                        //                        //组织节点的轨迹信息
                        //                        var p = $(this.node).offset();
                        //                        $('#tracktable').append(tablehtml);
                        //                        $('#trackinfo').offset({ top: p.top + this.attr('height') - 2, left: p.left });
                        //                        $('#trackinfo').show();
                        //                        return;

                        //增加到达时间,应完成时间.
                        var generWorkerLists = jdata.WF_GenerWorkerList;

                        if (generWorkerLists != null) {

                            for (var i = 0; i < generWorkerLists.length; i++) {

                                var gwl = generWorkerLists[i];
                                if (gwl.FK_Node != node.id)
                                    continue;

                                var rdt = gwl.RDT;
                                if(rdt!="" && rdt!="无")
                                 rdt = new Date(gwl.RDT).format('yyyy-MM-dd hh:mm');

                                var sdt = gwl.SDT;
                                if(sdt!="" && sdt!="无")
                                    sdt= new Date(gwl.SDT).format('yyyy-MM-dd hh:mm');

                                var cdt = gwl.CDT;
                                if(cdt!="" && cdt!="无")
                                cdt = new Date(gwl.CDT).format('yyyy-MM-dd hh:mm')

                                tablehtml += "<table style='width:300px;'>";
                                tablehtml += "<caption>" + gwl.FK_EmpText + "</capiton>";
                                tablehtml += "<tr style='background-color:InfoBackground' >";
                                tablehtml += "<td>任务下达日期</td>";
                                tablehtml += "<td>" + rdt + "</td>";
                                tablehtml += "</tr>";

                                tablehtml += "<tr style='background-color:InfoBackground' >";
                                tablehtml += "<td>应完成日期</td>";
                                tablehtml += "<td>" + sdt + "</td>";
                                tablehtml += "</tr>";


                                rdt = rdt.replace(/\-/g, "/");
                                rdt = new Date(rdt);

                                sdt = sdt.replace(/\-/g, "/");
                                sdt = new Date(sdt);

                                tablehtml += "<tr style='background-color:InfoBackground' >";
                                if (gwl.IsPass == 0) {
                                    tablehtml += "<td>还剩余</td>";
                                    tablehtml += "<td> " + GetSpanTime(rdt, sdt) + "</td>";
                                } else {
                                    tablehtml += "<td>实际完成</td>";
                                    tablehtml += "<td> " + cdt + "</td>";
                                }
                                tablehtml += "</tr>";


                                var cdt = cdt.replace(/\-/g, "/");
                                cdt = new Date(cdt);

                                tablehtml += "<tr style='background-color:InfoBackground' >";
                                if (gwl.IsPass == 1) {
                                    tablehtml += "<td>用时</td>";
                                    tablehtml += "<td> " + GetSpanTime(rdt, cdt) + "</td>";
                                }
                                tablehtml += "</tr>";

                                if (gwl.IsPass == 0) {
                                    tablehtml += "<tr style='background-color:InfoBackground' >";
                                    tablehtml += "<td>是否打开？</td>";

                                    if (gwl.IsRead == 1)
                                        tablehtml += "<td>是</td>";
                                    else
                                        tablehtml += "<td><font color=red>否</font></td>";
                                    tablehtml += "</tr>";
                                }

                                tablehtml += "<tr style='background-color:InfoBackground' >";
                                tablehtml += "<td>发送人</td>";
                                tablehtml += "<td>" + gwl.Sender + "</td>";
                                tablehtml += "</tr>";
                            }

                            tablehtml += "</table>";

                            //组织节点的轨迹信息
                            var p = $(this.node).offset();
                            $('#tracktable').append(tablehtml);
                            $('#trackinfo').offset({ top: p.top + this.attr('height') - 2, left: p.left });
                            $('#trackinfo').show();
                            return;
                        }

                        //重track里面获取数据.

                        //获得上一个节点发送的日志.

                        var Tracks = jdata.Track;
                        var nextTracks = Tracks;
                        var NDTo = "";

                        for (var i = 0; i < Tracks.length; i++) {
                            var track = Tracks[i];
                            if (track.ActionType == ActionType.FlowBBS)
                                continue;
                            if (track.ActionType == ActionType.WorkCheck)
                                continue;
                            var nodeId = node.id;
                            if (track.NDFrom == nodeId || track.NDTo == nodeId) {
                                NDTo = track.NDTo;
                                //node的最后两位判断是否为开始节点
                                var lastTwoBit = nodeId.toString().substring(nodeId.toString().length - 2);

                                tablehtml = "<table style='width:300px;'>";
                                if (track.NDFrom == nodeId)
                                    tablehtml += "<caption> " + track.EmpFromT + " </capiton>";
                                if (track.NDTo == nodeId && track.NDFrom != nodeId)
                                    tablehtml += "<caption> " + track.EmpToT + " </capiton>";
                                tablehtml += "<tr style='background-color:InfoBackground' >";
                                if (lastTwoBit == "01")
                                    tablehtml += "<td>任务启动日期</td>";
                                else
                                    tablehtml += "<td>任务下达日期</td>";
                                tablehtml += "<td>" + track.RDT + "</td>";
                                tablehtml += "</tr>";

                                //判断是否有考核时间
                                var mypk = node.id + "_" + uh["WorkID"] + "_" + track.FID + "_" + track.EmpFrom;
                                var chext = new Entity("BP.WF.Data.CH");
                                chext.SetPKVal(mypk);
                                var count = chext.RetrieveFromDBSources();
                                var SDT = "无";
                                if (count == 1 && lastTwoBit != "01")
                                    SDT = chext.SDT;
                                tablehtml += "<tr style='background-color:InfoBackground' >";
                                tablehtml += "<td>应完成日期</td>";
                                tablehtml += "<td>" + SDT + "</td>";

                                tablehtml += "</tr>";


                                var rdt = track.RDT.replace(/\-/g, "/");
                                rdt = new Date(rdt);



                                tablehtml += "<tr style='background-color:InfoBackground' >";
                                tablehtml += "<td>实际完成</td>";
                                var dtto = "";
                                // if (count == 1) {
                                //    dtto = chext.DTTo;
                                //最后流程
                                if (track.NDFrom == track.NDTo) {
                                    dtto = track.RDT;
                                } else {

                                    for (var k = 0; k < Tracks.length; k++) {
                                        var track1 = Tracks[k];
                                        if (track1.NDFrom == track.NDTo && track1.RDT >= track.RDT) {
                                            dtto = track1.RDT;
                                            break;
                                        }
                                    }

                                }
                                tablehtml += "<td id='cdt'> " + dtto + "</td>";
                                tablehtml += "</tr>";

                                dtto = dtto.replace(/\-/g, "/");
                                dtto = new Date(dtto);

                                tablehtml += "<tr style='background-color:InfoBackground' >";
                                tablehtml += "<td>用时</td>";
                                tablehtml += "<td> " + GetSpanTime(rdt, dtto) + "</td>";

                                tablehtml += "</tr>";
                                tablehtml += "<tr style='background-color:InfoBackground' >";
                                tablehtml += "<td>发送人</td>";
                                if (lastTwoBit == "01")
                                    tablehtml += "<td></td>"
                                else {
                                    for (var k = 0; k < Tracks.length; k++) {
                                        var track1 = Tracks[k];
                                        if (track1.ActionType == ActionType.FlowBBS)
                                            continue;
                                        if (track1.ActionType == ActionType.WorkCheck)
                                            continue;
                                        if (track1.NDTo == node.id) {
                                            tablehtml += "<td>" + track1.EmpFrom + "," + track1.EmpFromT + "</td>";
                                            break;
                                        }
                                    }
                                }
                                tablehtml += "</tr>";
                            }

                        }


                        tablehtml += "</table>";


                        //组织节点的轨迹信息
                        var p = $(this.node).offset();
                        $('#tracktable').append(tablehtml);
                        $('#trackinfo').offset({ top: p.top + this.attr('height') - 2, left: p.left });
                        $('#trackinfo').show();

                        return;


                        if (node.isTrackNode && node.currTrack.type == "FROM") {

                            node.rTrackText.attr({ "stroke": STYLE_NODE_COLOR_FORE_HOVER, "fill": getFillTextColor(STYLE_NODE_COLOR_FORE_HOVER) });

                            tablehtml +=
                                    '<tr>' +
                                    '   <td colspan="4" class="GroupTitle">轨迹信息</td>' +
                                    '</tr>';

                            var operID = ",";

                            $.each(node.tracks, function () {

                                var at = this.track.ACTIONTYPE;
                                if (at == 1 || at == 28 || at == 30) {
                                    operID = this.track.EmpFrom + "_" + this.track.NDTo + ",";
                                    return true;
                                }

                            });


                            $.each(node.tracks, function () {

                                if (this.type == "TO") {
                                    return true;
                                }

                                var val = this.track.ACTIONTYPETEXT;

                                var at = this.track.ACTIONTYPE;

                                if (val == "协作") {
                                    operID = this.track.EmpFrom + "_" + this.track.NDTo;
                                    return true;
                                }

                                if (val == "前进" && node.isTrackNode.length != 1) {
                                    operID = this.track.EmpFrom + "_" + this.track.NDTo;
                                    return true;
                                }

                                //仅仅显示已经审批过的人员记录, 对于打开过，但是没有审批的，不显示.
                                var myoperID = this.track.EmpFrom + "_" + this.track.NDTo;

                                if (at == 22 || val == "审核") {
                                    if (operID.indexOf(myoperID) == 0) {
                                        return true;
                                    }
                                }

                                var emp = this.track.EmpToT;
                                if (emp.indexOf('(') >= 0) {
                                    return true;
                                }

                                tablehtml +=
                                    '<tr>' +
                                    '   <td style="width:120px">' + this.track.RDT + '</td>' +
                                    '   <td style="width:200px">' + this.track.ActionType + '</td>' +
                                    '   <td style="width:50px">' + this.track.EmpToT + '</td>' +
                                    '   <td><font color=green>' + this.track.Msg.replace(/~/g, "'") + '</font></td>' +
                                    '</tr>';
                            });
                        }
                        else if (node.rTrackText) { //added by liuxc,2016-03-16                            
                            node.rTrackText.attr({ "stroke": STYLE_NODE_COLOR_FORE_HOVER, "fill": getFillTextColor(STYLE_NODE_COLOR_FORE_HOVER) });
                        }
                        else if (node.rPossibleText) { //added by liuxc,2016-04-15
                            node.rPossibleText.attr({ "stroke": STYLE_NODE_COLOR_FORE_HOVER, "fill": getFillTextColor(STYLE_NODE_COLOR_FORE_HOVER) });
                        }

                        if (work_ID == "0") {
                            return;
                        }

                        var subcount = 0;

                        isSubFlowNode = false;
                        var subflows = getSubFlows(node.id);
                        for (var sf in subflows) {
                            isSubFlowNode = true;
                            tablehtml +=
                                        '<tr>' +
                                        '   <td colspan="4" class="GroupTitle">' + subflows[sf].Name + '</td>' +
                                        '</tr>';

                            $.each(subflows[sf].Flows, function () {
                                tablehtml +=
                                            '<tr>' +
                                            '   <td style="width:120px;">' + this.RDT + '</td>' +
                                            '   <td style="width:200px"><a href="' + this.Url + '" target="_blank" style="color:' + STYLE_NODE_COLOR_FORE_HOVER + '">' + this.Title + '</a></td>' +
                                            '   <td style="width:50px;">' + this.WFStaText + '</td>' +
                                            '   <td>' + this.NodeName + '</td>' +
                                            '</tr>';
                            });
                        }


                        if (tablehtml.length > 0) {

                            tablehtml = "<table>" + tablehtml;
                            tablehtml += "</table>";

                            //组织节点的轨迹信息
                            var p = $(this.node).offset();
                            $('#tracktable').append(tablehtml);
                            $('#trackinfo').offset({ top: p.top + this.attr('height') - 2, left: p.left });
                            $('#trackinfo').show();
                        }
                    }
                }, function () {
                    var node = rFlow.getNodeByRIconId(this.id);
                    if (node != null) {
                        node.rBorder.attr({ "stroke": node.currTrack ? STYLE_NODE_BORDER_COLOR_TRACK : node.rBorderColor, "stroke-width": STYLE_NODE_BORDER_WIDTH_NORMAL });
                        node.rText.attr({ "stroke": node.currTrack ? STYLE_NODE_COLOR_FORE_TRACK : STYLE_NODE_COLOR_FORE, "fill": getFillTextColor(node.currTrack ? STYLE_NODE_COLOR_FORE_TRACK : STYLE_NODE_COLOR_FORE) });

                        if (node.isTrackNode && node.currTrack.type == "FROM") {
                            node.rTrackText.attr({ "stroke": STYLE_NODE_TRACK_FORE_COLOR, "fill": getFillTextColor(STYLE_NODE_TRACK_FORE_COLOR) });
                        }
                        else if (node.rTrackText) { //added by liuxc,2016-03-16
                            node.rTrackText.attr({ "stroke": STYLE_NODE_TRACK_FORE_COLOR, "fill": getFillTextColor(STYLE_NODE_TRACK_FORE_COLOR) });
                        }
                        else if (node.rPossibleText) { //added by liuxc,2016-04-15
                            node.rPossibleText.attr({ "stroke": STYLE_NODE_TRACK_FORE_COLOR, "fill": getFillTextColor(STYLE_NODE_TRACK_FORE_COLOR) });
                        }

                        if (isSubFlowNode == false) {
                            $('#trackinfo').offset({ top: 0, left: 0 });
                            $('#trackinfo').hide();
                        }
                    }
                });

                rNode.rIcon.drag(iconMove, iconDrag, iconUp);

                //加入到流程节点.
                rFlow.nodes.push(rNode);

            });

            //绘制节点的连线
            var fromNode, toNode, tracknode;
            $.each(datas.WF_Direction, function () {

                rDir = new RDirection(this.Node, this.ToNode, this.DirType, this.IsCanBack);
                rDir.FromNode = rFlow.getNode(this.Node);
                rDir.ToNode = rFlow.getNode(this.ToNode);

                //计算连线的起始点
                rDir.rPath = r.drawArr({
                    rStart: rDir.FromNode.rBorder,
                    rEnd: rDir.ToNode.rBorder,
                    rDots: getDots(this.Dots),
                    node: this.Node,
                    tonode: this.ToNode,
                    pathColor: datas.Track.findBy2Field("NDFROM", rDir.FromNode.id, "NDTO", rDir.ToNode.id) != null ? STYLE_LINE_TRACK_COLOR : STYLE_LINE_COLOR    //&& rDir.ToNode.isTrackNode,edited by liuxc,2016-03-15,工作到哪个节点的轨迹都显示出来
                });

                arrs.push(rDir.rPath);

                rFlow.dirs.push(rDir);
            });

            //绘制标签
            $.each(datas.WF_LabNote, function () {
                rLabel = new RLabel(this.MyPK, this.Name, this.X, this.Y);
                rLabel.rText = r.text(this.X, this.Y + STYLE_FONT_SIZE_LABEL, this.Name);
                rLabel.rText.attr({ "stroke": STYLE_LABEL_COLOR_FORE, "fill": getFillTextColor(STYLE_LABEL_COLOR_FORE), "font-size": STYLE_FONT_SIZE_LABEL, "text-anchor": "start" });
                rLabel.rText.toFront();
            });
        }

        function getMaxSize(nodes, dirs) {

            /// <summary>获取所有节点坐标最大值</summary>
            /// <param name="nodes" Type="Array">节点数组</param>
            /// <param name="dirs" Type="Array">连线数组</param>
            var xmax = 0;
            var ymax = 0;
            var ps, pss;

            $.each(nodes, function () {
                xmax = Math.max(xmax, this.X);
                ymax = Math.max(ymax, this.Y);
            });

            $.each(dirs, function () {
                if (this.DOTS && this.DOTS.length > 0) {
                    ps = this.DOTS.split('@');

                    for (var i = 0; i < ps.length; i++) {
                        if (ps[i].length == 0) {
                            continue;
                        }

                        pss = ps[i].split(',');
                        xmax = Math.max(xmax, parseFloat(pss[0]));
                        ymax = Math.max(ymax, parseFloat(pss[1]));
                    }
                }
            });

            return { X: xmax, Y: ymax };
        }

        function getSubFlows(nodeId) {

            var subflows = {};
            var flows = "";
            var subflow;

            $.each(jdata.FLOWINFO, function () {
                if (this.PNodeID == 0 || this.PNodeID != nodeId) {
                    return true;
                }

                if (flows.indexOf(this.FK_Flow + ",") == -1) {
                    flows += this.FK_Flow + ",";
                    subflow = { No: this.FK_Flow, Name: this.FlowName, Flows: [] };
                    subflows["F" + this.FK_Flow] = subflow;
                }
                else {
                    subflow = subflows["F" + this.FK_Flow];
                }

                subflow.Flows.push({ Title: this.Title, NodeName: this.NodeName, WFStaText: this.WFStaText, RDT: this.RDT, Url: "./OneWork.htm?CurrTab=Truck&FK_Flow=" + this.FK_Flow + "&FK_Node=" + this.FK_Node + "&WorkID=" + this.WorkID + "&FID=0" });
            });

            return subflows;
        }

        function getDots(dotStr) {
            if (!dotStr || dotStr.length == 0) {
                return [];
            }

            var dots = [];
            var strs = dotStr.split('@');
            var sub;

            $.each(strs, function () {
                if (this.length == 0) {
                    return true;
                }

                sub = this.split(',');

                if (sub.length != 2) {
                    return true;
                }

                dots.push({ x: parseFloat(sub[0]), y: parseFloat(sub[1]) });
            });

            return dots;
        }

        function breakstr(str, rowWordsCount) {

            /// <summary>获取指定Raphael Text字符串换行显示字符串</summary>
            /// <param name="str" Type="String">要换行的字符串</param>            
            /// <param name="rowWordsCount" Type="Number">每行字符数</param>            
            var newstr = '';
            for (var i = 0; i < str.length; i++) {
                newstr += (i + 1) % rowWordsCount == 0 ? (str.charAt(i) + '\n') : str.charAt(i);
            }

            return newstr;
        }

        function getFillTextColor(strokeColor) {
            /// <summary>获取指定字体绘制颜色的填充颜色</summary>
            /// <param name="time" Type="String">字体绘制颜色</param>
            return strokeColor == "none" ? "black" : strokeColor;
        }

        function getChineseDateTime(time) {

            if (!time || time.length < 10) {
                return '';
            }

            var myDate = new Date(Date.parse(time.replace(/-/g, "/")));
            return myDate.toLocaleString();

            //alert(myDate);
            //alert(myDate.getMonth());
            //return myDate.getMonth() + "月" + myDate.getDate() + "日 " + myDate.getHours() + ":" + myDate.getMinutes() + ":" + myDate.getSeconds() ;
        }


        function iconDrag() {
            this.ox = this.attr("x");
            this.oy = this.attr("y");
            this.animate({ "fill-opacity": 0.5 }, 500);

            //记录与ICON绑定的其他对象的原始坐标
            dragNode = rFlow.getNodeByRIconId(this.id);
            dragBorderPointStart = { x: dragNode.rBorder.attr("x"), y: dragNode.rBorder.attr("y") };
            dragTextPointStart = { x: dragNode.rText.attr("x"), y: dragNode.rText.attr("y") };

            if (dragNode.isTrackNode) {
                dragTrackTextPointStart = { x: dragNode.rTrackText.attr("x"), y: dragNode.rTrackText.attr("y") };
            }
            else if (dragNode.rTrackText) { //added by liuxc,2016-03-16
                dragTrackTextPointStart = { x: dragNode.rTrackText.attr("x"), y: dragNode.rTrackText.attr("y") };
            }
            else if (dragNode.rPossibleText) { //added by liuxc,2016-04-15
                dragPossibleTextPointStart = { x: dragNode.rPossibleText.attr("x"), y: dragNode.rPossibleText.attr("y") };
            }
        }

        function iconMove(dx, dy) {
            var att = { x: this.ox + dx, y: this.oy + dy };
            this.attr(att);

            //动态修改与ICON绑定的其他对象的坐标
            dragNode.rBorder.attr({ x: dragBorderPointStart.x + dx, y: dragBorderPointStart.y + dy });
            dragNode.rText.attr({ x: dragTextPointStart.x + dx, y: dragTextPointStart.y + dy });

            if (dragNode.isTrackNode) {
                dragNode.rTrackText.attr({ x: dragTrackTextPointStart.x + dx, y: dragTrackTextPointStart.y + dy });
            }
            else if (dragNode.rTrackText) { //added by liuxc,2016-03-16
                dragNode.rTrackText.attr({ x: dragTrackTextPointStart.x + dx, y: dragTrackTextPointStart.y + dy });
            }
            else if (dragNode.rPossibleText) { //added by liuxc,2016-04-15
                dragNode.rPossibleText.attr({ x: dragPossibleTextPointStart.x + dx, y: dragPossibleTextPointStart.y + dy });
            }

            //重绘与该节点相连的连接线
            for (var i = arrs.length; i--; ) {
                if (arrs[i].rStart.id == dragNode.rBorder.id || arrs[i].rEnd.id == dragNode.rBorder.id) {
                    r.drawArr(arrs[i]);
                }
            }
        }

        function iconUp() {
            this.animate({ "fill-opacity": 1 }, 500);

            if (dragNode.isTrackNode) {
                var p = $(dragNode.rIcon.node).offset();
                $('#trackinfo').offset({ top: p.top + dragNode.rIcon.attr('height') + 2, left: p.left });
                dragNode = null;
            }
        }

        function RFlow(sFlowNo) {
            /// <summary>流程</summary>
            /// <param name="sFlowNo" Type="String">流程编号</param>
            this.no = sFlowNo;
            this.nodes = new Array();
            this.labels = new Array();
            this.dirs = new Array();

            if (typeof RFlow._initialized == "undefined") {
                RFlow.prototype.getNode = function (nodeid) {
                    /// <summary>根据指定节点ID获取该结点使用Raphael绘制的对象</summary>
                    /// <param name="nodeid" Type="Int">流程编号</param>
                    for (i in this.nodes) {
                        if (this.nodes[i].id == nodeid) {
                            return this.nodes[i];
                        }
                    }

                    return null;
                }

                RFlow.prototype.getNodeByRIconId = function (raphaelid) {
                    /// <summary>根据绘制的节点中的ICON对象的id获取该结点使用Raphael绘制的对象</summary>
                    /// <param name="raphaelid" Type="Int">流程编号</param>
                    for (i in this.nodes) {
                        if (this.nodes[i] && this.nodes[i].rIcon && this.nodes[i].rIcon.id == raphaelid) {
                            return this.nodes[i];
                        }
                    }

                    return null;
                }
            }
        }

        /// <summary>节点</summary>
        /// <param name="iNodeID" Type="Int">节点ID</param>
        /// <param name="sNodeName" Type="String">节点名称</param>
        /// <param name="iX" Type="Int">节点中心点X坐标</param>
        /// <param name="iY" Type="Int">节点中心点Y坐标</param>
        function RNode(iNodeID, sNodeName, iX, iY) {

            this.id = iNodeID;
            this.name = sNodeName;
            this.x = iX;
            this.y = iY;
            this.icon = '';
            this.nodePosType = 0;
            this.hisToNDs = '';
            this.rBorder = null;
            this.rIcon = null;
            this.rText = null;
            this.rTrackText = null;
            this.rBorderColor = 'black';
            this.isTrackNode = false;
            this.tracks = null;
            this.currTrack = null;
            this.rPossibleText = null;
            this.rPossible = null;
        }

        function RLabel(sPk, sLabelName, iX, iY) {
            /// <summary>标签</summary>
            /// <param name="sPk" Type="String">MyPk</param>
            /// <param name="sLabelName" Type="String">标签文本</param>
            /// <param name="iX" Type="Int">标签左上角X坐标</param>
            /// <param name="iY" Type="Int">标签左上角Y坐标</param>
            this.mypk = sPk;
            this.name = sLabelName;
            this.x = iX;
            this.y = iY;
            this.rText = null;
        }

        function RDirection(iFromNodeID, iToNodeID, iDirType, iIsCanBack) {
            /// <summary>结点连接线</summary>
            /// <param name="iFromNodeID" Type="Int">开始节点ID</param>
            /// <param name="iToNodeID" Type="Int">结束节点ID</param>
            /// <param name="iDirType" Type="Int">节点类型 0-前进 1-返回</param>
            /// <param name="iIsCanBack" Type="Int">是否可以原路返回</param>
            this.fromNodeID = iFromNodeID;
            this.toNodeID = iToNodeID;
            this.dirType = iDirType;
            this.isCanBack = iIsCanBack;
            this.rPath = null;
            this.rPathColor = STYLE_LINE_COLOR;
            this.FromNode = null;
            this.ToNode = null;
            this.LinkText = null;
        }

        function getMaxInArray(arr, propName) {
            /// <summary>获取指定对象数组中指定属性的最大值</summary>
            /// <param name="arr" Type="Array">对象数组</param>
            /// <param name="propName" Type="String">属性名称</param>
            var max = 0;

            $.each(arr, function () {
                for (prop in this) {
                    if (prop == propName && !isNaN(this[prop])) {
                        max = Math.max(max, this[prop]);
                    }
                }
            });

            return max;
        }

        function getTracksByFromNode(tracks, nodeId) {
            /// <summary>从轨迹集合中获取指定节点的轨迹集合</summary>
            /// <param name="tracks" Type="Array">所有轨迹数组</param>
            /// <param name="nodeId" Type="Int">指定结点的ID</param>
            var ts = new Array();

            $.each(tracks, function () {
                if (this.NDFrom == nodeId) {
                    ts.push({ track: this, type: "FROM" });
                }
                else if (this.NDTo == nodeId) {
                    ts.push({ track: this, type: "TO" });
                }
            });

            return ts;
        }

        function getTrackForCurrNode(tracks) {
            /// <summary>获取此节点轨迹集合中的用于绘制到此节点的轨迹</summary>
            /// <param name="tracks" Type="Array">轨迹数组</param>
            for (var i = tracks.length - 1; i >= 0; i--) {
                if (tracks[i].track.ActionType == 1 ||    //前进
                tracks[i].track.ActionType == 2 ||    //退回
                tracks[i].track.ActionType == 6 ||    //分流前进
                tracks[i].track.ActionType == 7 ||    //合流前进
                tracks[i].track.ActionType == 8 ||    //流程正常结束
                tracks[i].track.ActionType == 11 ||   //子线程前进
                tracks[i].track.ActionType == 26 ||   //自动条转的方式向下发送
                tracks[i].track.ActionType == 27 ||   //队列发送
                tracks[i].track.ActionType == 28) {   //协作发送
                    return tracks[i];
                }
            }

            return tracks[tracks.length - 1];
        }

        //获取组成箭头的三条线段的路径
        function getArr(x1, y1, x2, y2, size, dots) {
            var angle;

            if (dots.length > 0) {
                angle = Raphael.angle(dots[dots.length - 1].x, dots[dots.length - 1].y, x2, y2); //得到两点之间的角度
            }
            else {
                angle = Raphael.angle(x1, y1, x2, y2);
            }

            var a45 = Raphael.rad(angle - 45); //角度转换成弧度
            var a45m = Raphael.rad(angle + 45);
            var x2a = x2 + Math.cos(a45) * size;
            var y2a = y2 + Math.sin(a45) * size;
            var x2b = x2 + Math.cos(a45m) * size;
            var y2b = y2 + Math.sin(a45m) * size;

            var result = [];
            result.push("M"); result.push(x1); result.push(y1);

            $.each(dots, function () {
                result.push("L"); result.push(this.x); result.push(this.y);
            });

            result.push("L"); result.push(x2); result.push(y2);
            result.push("L"); result.push(x2a); result.push(y2a);
            result.push("M"); result.push(x2); result.push(y2);
            result.push("L"); result.push(x2b); result.push(y2b);

            //var result = ["M", x1, y1, "L", x2, y2, "L", x2a, y2a, "M", x2, y2, "L", x2b, y2b];
            return result;
        }

        function getStartEnd(obj1, obj2) {
            var bb1 = obj1.getBBox(),
                bb2 = obj2.getBBox();
            var p = [
                    { x: bb1.x + bb1.width / 2, y: bb1.y - 1 },
                    { x: bb1.x + bb1.width / 2, y: bb1.y + bb1.height + 1 },
                    { x: bb1.x - 1, y: bb1.y + bb1.height / 2 },
                    { x: bb1.x + bb1.width + 1, y: bb1.y + bb1.height / 2 },
                    { x: bb2.x + bb2.width / 2, y: bb2.y - 1 },
                    { x: bb2.x + bb2.width / 2, y: bb2.y + bb2.height + 1 },
                    { x: bb2.x - 1, y: bb2.y + bb2.height / 2 },
                    { x: bb2.x + bb2.width + 1, y: bb2.y + bb2.height / 2 }
                ];
            var d = {}, dis = [];
            for (var i = 0; i < 4; i++) {
                for (var j = 4; j < 8; j++) {
                    var dx = Math.abs(p[i].x - p[j].x),
                        dy = Math.abs(p[i].y - p[j].y);
                    if (
                         (i == j - 4) ||
                         (((i != 3 && j != 6) || p[i].x < p[j].x) &&
                         ((i != 2 && j != 7) || p[i].x > p[j].x) &&
                         ((i != 0 && j != 5) || p[i].y > p[j].y) &&
                         ((i != 1 && j != 4) || p[i].y < p[j].y))
                       ) {
                        dis.push(dx + dy);
                        d[dis[dis.length - 1]] = [i, j];
                    }
                }
            }
            if (dis.length == 0) {
                var res = [0, 4];
            } else {
                res = d[Math.min.apply(Math, dis)];
            }
            var result = {};
            result.start = {};
            result.end = {};
            result.start.x = p[res[0]].x;
            result.start.y = p[res[0]].y;
            result.end.x = p[res[1]].x;
            result.end.y = p[res[1]].y;
            return result;
        }

        Raphael.fn.drawArr = function (raphaelObj) {
            /// <summary>绘制带箭头的连接线</summary>
            /// <param name="raphaelObj" Type="Raphael Element">要绘制的连接的信息对象，包括rStart[开始对象]/rEnd[结束对象]/pathColor[连接线颜色]</param>
            //如果有折线点，则先将点画出，再计算开始结束点
            var point = { start: { x: 0, y: 0 }, end: { x: 0, y: 0} };
            var dots = [];
            var lps = getLinePots(raphaelObj.node, raphaelObj.tonode);
            var d;

            if (raphaelObj.rDots.length > 0) {
                if (lps.length == 0) {
                    dots = [];

                    $.each(raphaelObj.rDots, function () {
                        d = { rCircle: r.circle(this.x, this.y, 2), node: raphaelObj.node, tonode: raphaelObj.tonode };
                        linedots.push(d);
                        dots.push(d);
                    });
                }
                else {
                    dots = lps;
                }

                var p1 = getStartEnd(raphaelObj.rStart, dots[0].rCircle);
                var p2 = getStartEnd(dots[dots.length - 1].rCircle, raphaelObj.rEnd);

                point.start.x = p1.start.x;
                point.start.y = p1.start.y;
                point.end.x = p2.end.x;
                point.end.y = p2.end.y;
            }
            else {
                point = getStartEnd(raphaelObj.rStart, raphaelObj.rEnd);
            }

            var path1 = getArr(point.start.x, point.start.y, point.end.x, point.end.y, 8, raphaelObj.rDots);
            var pathColor;

            if (raphaelObj.arrPath) {
                raphaelObj.arrPath.attr({ path: path1 });
            }
            else {
                if (raphaelObj.pathColor) {
                    pathColor = raphaelObj.pathColor;
                }
                else {
                    pathColor = STYLE_LINE_COLOR;
                }

                raphaelObj.arrPath = this.path(path1);
                raphaelObj.arrPath.attr({ "stroke": pathColor, "stroke-width": STYLE_LINE_WIDTH }); //设置"arrow-end": "classic-wide-long"有问题

                raphaelObj.arrPath.hover(function () {
                    this.attr("stroke", STYLE_LINE_HOVER_COLOR);
                }, function () {
                    this.attr("stroke", pathColor);
                });
            }

            return raphaelObj;
        };

        function getLinePots(node, tonode) {
            if (!linedots) {
                return [];
            }

            var ps = [];

            for (var i = 0; i < linedots.length; i++) {
                if (linedots[i].node == node && linedots[i].tonode == tonode) {
                    ps.push(linedots[i]);
                }
            }

            return ps;
        }

        function checkUrl(url) {

            /// <summary>判断远程路径是否可以连接成功</summary>
            /// <param name="url" Type="String">远程路径url</param>

            var isSuccess;

            $.ajax({
                type: 'GET',
                cache: false,   //不下载远程url
                async: false,   //同步
                url: url,
                data: '',
                success: function () {
                    isSuccess = true;
                },
                error: function () {
                    isSuccess = false;
                }
            });

            return isSuccess;
        }

        function GetSpanTime(date1, date2) {
            ///<summary>计算date2-date1的时间差，返回使用“x天x小时x分x秒”形式的字符串表示</summary>
            var date3 = date2.getTime() - date1.getTime();  //时间差秒
            var str = '';
            //计算出相差天数
            var days = Math.floor(date3 / (24 * 3600 * 1000));
            if (days > 0) {
                str += days + '天';
            }

            //计算出小时数
            var leave1 = date3 % (24 * 3600 * 1000);   //计算天数后剩余的毫秒数
            var hours = Math.floor(leave1 / (3600 * 1000));
            if (hours > 0) {
                str += hours + '小时';
            }

            //计算相差分钟数
            var leave2 = leave1 % (3600 * 1000);         //计算小时数后剩余的毫秒数
            var minutes = Math.floor(leave2 / (60 * 1000));
            if (minutes > 0) {
                str += minutes + '分';
            }

            if (str.length == 0) {
                var leave3 = leave2 % (60 * 1000);
                var seconds = Math.floor(leave3 / 1000);

                str += seconds + '秒';

                if (seconds == NaN)
                    return date1 + "," + date2;
                return str;
            }

            return str;
        }

        //时间格式
        Date.prototype.format = function (format) {
            var date = {
                "M+": this.getMonth() + 1,
                "d+": this.getDate(),
                "h+": this.getHours(),
                "m+": this.getMinutes(),
                "s+": this.getSeconds(),
                "q+": Math.floor((this.getMonth() + 3) / 3),
                "S+": this.getMilliseconds()
            };
            if (/(y+)/i.test(format)) {
                format = format.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length));
            }
            for (var k in date) {
                if (new RegExp("(" + k + ")").test(format)) {
                    format = format.replace(RegExp.$1, RegExp.$1.length == 1
                            ? date[k] : ("00" + date[k]).substr(("" + date[k]).length));
                }
            }
            return format;
        }
    </script>
    <div id="holder">
    </div>
    <div id="trackinfo" style="display: none; position: absolute; width: 260px; height: auto;background-color: #fff">
        <table id="tracktable" class="Table" cellpadding="0" cellspacing="0" border="1" style="width: 100%">
        </table>
    </div>
</body>
</html>
